library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity RecHandle is
	port
	( 	
		clk: in std_logic;
		reset: in std_logic;
		
		Data_Read: OUT STD_LOGIC; --4 ports out to RcvPortCycle
		Length_Read: OUT STD_LOGIC;
		Packet_Finished: OUT STD_LOGIC;
		--Packet_Error: OUT STD_LOGIC;
		
		
		Data: in std_logic_vector(7 downto 0); --6 ports in from RcvPortCycle
		Packet_Length: in std_logic_vector(11 downto 0); --include valid
		Connection_Ready: in std_logic;
		--Check_Counter: in std_logic_vector(11 downto 0);
		Input_Port_Number: in std_logic_vector(1 downto 0);
		--Data_Valid: in std_logic;
		
		
		--FIFO_Empty: in std_logic; --1 port in from data FIFO
		FIFO_Full: in std_logic;  --added for monitoring the data FIFO
		
		Data_Output: out std_logic_vector(7 downto 0); --3 ports to data FIFO
		Data_wrreq: out std_logic;
				
		Address_FIFO_Empty: in std_logic; -- 1 port from Addr FIFO
		
		Address_Output: out std_logic_vector(7 downto 0); --3 ports to Addr FIFO
		Address_wrreq: out std_logic;
		Address_InputPortNumber: out std_logic_vector(1 downto 0);
				
		Length_FIFO_Full:in std_logic; --1 port from Length FIFO
		
		Length_FIFO_output:out std_logic_vector(10 downto 0); --2 ports to Length FIFO
		Length_FIFO_wrreq:out std_logic

	);
end RecHandle;

architecture RecHandle_arch of RecHandle is
	type RecHandle_state is
			(idle, lengthread, lengthwrite, addressread, dataread, datadrop, packetend);
	signal state_reg, state_next: RecHandle_state;
	
	signal Rcv_Counter,rcv_counter_next: unsigned (10 downto 0);--internal
	--signal PacketBegin:std_logic;
	--signal PacketEnd:std_logic;
	
	signal Data_Valid:std_logic;
	
	signal Packet_FinishedA: std_logic;
--	signal Packet_ErrorA: std_logic;
	
	signal Data_OutputA: std_logic_vector(7 downto 0);
	signal Data_Output_Drop: std_logic_vector(7 downto 0); --drop packets
	signal Packet_Length_OutputA: std_logic_vector(10 downto 0);--packet length
	signal Packet_Length_OutputA_next: std_logic_vector(10 downto 0);--packet length

	
	signal Address_OutputA: std_logic_vector(7 downto 0);
	
	signal Length_FIFO_outputA:std_logic_vector(10 downto 0);
	
--------------------------------------
	signal temp_port_number,temp_port_number_next: std_logic_vector(1 downto 0);
	
	
	
begin
	--state register
	process(clk, reset)
	begin
		if (reset='1')then
			state_reg<=idle;
		elsif (clk' event and clk='1') then
			state_reg<=state_next;			
		    rcv_counter<=rcv_counter_next;	
		    temp_port_number<=temp_port_number_next;
		    Packet_Length_OutputA<=Packet_Length_OutputA_next;
		end if;
	end process;
	
    --next_counter logic
    process(rcv_counter,state_reg)
    begin
       if(state_reg=datadrop or state_reg=addressread or state_reg=dataread)then rcv_counter_next<=rcv_counter+1;
       else rcv_counter_next<=(others=>'0');
       end if;
    end process;	

    --inputs
    temp_port_number_next<=Input_Port_Number when (state_reg=idle and connection_ready='1') else
                           "00" when(state_reg=idle and connection_ready='0') else
                           temp_port_number;
                           
    --next Packet_Length_OutputA logic
    process(state_reg, Packet_Length_OutputA, Packet_Length)
	begin
		if(state_reg=idle) then
			Packet_Length_OutputA_next<="00000000000";
		elsif(state_reg=lengthread) then
			Packet_Length_OutputA_next<=Packet_Length(10 downto 0);
		else Packet_Length_OutputA_next<=Packet_Length_OutputA;
		end if;
	end process;
	
	--next-state logic
	process(state_reg, Connection_Ready, Rcv_Counter,Data_Valid, FIFO_Full, Address_FIFO_Empty, Packet_Length_OutputA,Length_FIFO_Full)
	begin
		case state_reg is
			when idle =>
				if (Connection_Ready='1' and FIFO_Full='0'and Address_FIFO_Empty='1'and Length_FIFO_Full='0') then
					state_next<=lengthread;
				else
					state_next<=idle;
				end if;
				
			when lengthread =>
				if (Data_Valid='1') then
					state_next<=lengthwrite;
				else
					state_next<=datadrop;
				end if;
				
			when datadrop =>
				if (Rcv_Counter=(unsigned (Packet_Length_OutputA)-1)) then
					state_next<=packetend;
				else
					state_next<=datadrop;
				end if;
				
			when lengthwrite =>
				state_next<=addressread;
							
			when addressread =>
				if (Rcv_Counter="00000001011") then
					state_next<=dataread;
				else
					state_next<=addressread;
				end if;
				
			when dataread =>
				if (Rcv_Counter=(unsigned (Packet_Length_OutputA)-1)) then
					state_next<=packetend;
				else
					state_next<=dataread;
				end if;
				
			when packetend =>
				state_next<=idle;
		end case;
	end process;

	--Moore output logic, read or write request and finish
	process(state_reg)
    begin
       case state_reg is
           when idle=>
				Length_Read <='0';
				Data_Read <= '0';
                Packet_Finished<='0';
                Address_wrreq<='0';
                Data_wrreq<='0';
           when lengthread=>
				Length_Read <='1';
				Data_Read <= '0'; 
                Packet_Finished<='0';
                Address_wrreq<='0';
                Data_wrreq<='0';
           when datadrop =>
				Length_Read <='0';
				Data_Read <= '1';
                Packet_Finished<='0';
                Address_wrreq<='0';
                Data_wrreq<='0';  
           when lengthwrite =>
				Length_Read <='0';
				Data_Read <= '0';
                Packet_Finished<='0'; 
                Address_wrreq<='0'; 
                Data_wrreq<='0';              
           when addressread =>
				Length_Read <='0';
				Data_Read <= '1';
                Packet_Finished<='0';
                Address_wrreq<='1';
                Data_wrreq<='1';
           when dataread =>
				Length_Read <='0';
				Data_Read <= '1';
                Packet_Finished<='0';
                Address_wrreq<='0';
                Data_wrreq<='1';
           when packetend =>
				Length_Read <='0';
				Data_Read <= '0';
                Packet_Finished<='1';
                Address_wrreq<='0';
                Data_wrreq<='0';
       end case;
    end process;

	--Meely output logic
    process(state_reg, FIFO_Full, Connection_Ready, Address_FIFO_Empty, Input_Port_Number, Packet_Length, Data_Valid, Data, Length_FIFO_Full,Packet_Length_OutputA)
	begin
		case state_reg is
			when idle =>				
				Data_Valid<='1';
				Address_OutputA<="00000000";
				Data_OutputA<="00000000";
				Length_FIFO_wrreq<='0';
								
			when lengthread =>				
				Data_Valid<=Packet_Length(11);
				Address_OutputA<="00000000";
				Data_OutputA<="00000000";						
				Length_FIFO_wrreq<='0';		
	
			when datadrop =>
				Data_Valid<='1';
				Address_OutputA<="00000000";
				Data_OutputA<=Data;
				Length_FIFO_wrreq<='0';
				
			when lengthwrite =>
				Data_Valid<='1';
				Address_OutputA<="00000000";
			    Length_FIFO_wrreq<='1';
			    Data_OutputA<="00000000";				
			
			when addressread =>
				Data_Valid<='1';
				Data_OutputA<=Data;
				Address_OutputA<=Data;
				Length_FIFO_wrreq<='0';
				
			
			when dataread =>
				Data_Valid<='1';			    
				Address_OutputA<="00000000";
				Data_OutputA<=Data;
				Length_FIFO_wrreq<='0';
				
			when packetend =>
				Data_Valid<='1';
				Address_OutputA<="00000000";
			    Length_FIFO_wrreq<='0';
			    Data_OutputA<="00000000";				
		end case;
	end process;
	
	--outputs to forwards
	Data_Output<=Data_OutputA;
	Length_FIFO_output<=Packet_Length_OutputA;	
	Address_Output<=Address_OutputA;	
	Address_InputPortNumber<=temp_port_number;
	
	
end RecHandle_arch;
	
				
			
			
				
			
			
			
			
			

				
				
	